package com.kgc.dubbo.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.kgc.dubbo.entity.QgGoods;
import com.kgc.dubbo.entity.QgGoodsTempStock;
import com.kgc.dubbo.entity.QgOrder;
import com.kgc.dubbo.entity.QgUser;
import com.kgc.dubbo.exception.GoodsException;
import com.kgc.dubbo.service.LocalGoodsService;
import com.kgc.dubbo.service.QgGoodsService;
import com.kgc.dubbo.service.QgGoodsTempStockService;
import com.kgc.dubbo.service.QgOrderService;
import com.kgc.dubbo.utils.Constants;
import com.kgc.dubbo.utils.EmptyUtils;
import com.kgc.dubbo.utils.IdWorker;
import com.kgc.dubbo.utils.compoent.ActiveMQutil;
import com.kgc.dubbo.utils.compoent.RedisTools;
import com.kgc.dubbo.vo.QgGoodsVO;
import com.kgc.dubbo.vo.RespResult;
import com.kgc.dubbo.vo.SnapupGoodsVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class LocalGoodsServiceImpl implements LocalGoodsService {
    @Reference
    private QgGoodsService qgGoodsService;
    @Reference
    private QgGoodsTempStockService qgGoodsTempStockService;
    @Reference
    private QgOrderService qgOrderService;
    @Autowired
    private RedisTools redisTools;
    @Autowired
    private ActiveMQutil activeMQutil;
    @Override
    public RespResult getGoodsById(String id) throws Exception {
        //1.根据商品编号去redis中查询商品信息
        QgGoodsVO goodsVO = redisTools.getObject(Constants.GOODS_PREFIX + id, QgGoodsVO.class);
        if(EmptyUtils.isNotEmpty(goodsVO)){
            return RespResult.ok(goodsVO);
        }
        //1.根据商品编号查询商品信息
        QgGoods qgGoods = qgGoodsService.getQgGoodsById(id);
        if(EmptyUtils.isEmpty(qgGoods)){
            return RespResult.build(GoodsException.GOODS_NOT_FOUND.getCode(),
                    GoodsException.GOODS_NOT_FOUND.getMessage());
        }
        //2.在qgGoodsTempStock表中查询status为锁定装袋和待支付完成的记录数
        //创建查询条件：
        Map<String,Object> params = new HashMap<>();
        params.put("goodsId",id);
        params.put("lockstock", Constants.LOCK_STOCK);
        Integer totalCount = qgGoodsTempStockService.getQgGoodsTempStockCountByMap(params);
        //3计算当前的库存等于商品表中的原始库存减去第二部查询出来的数据
        Integer currentstock = qgGoods.getStock()-totalCount;
        //4.封装数据
        goodsVO = new QgGoodsVO();
        BeanUtils.copyProperties(qgGoods,goodsVO);
        goodsVO.setCurrentStock(currentstock);
        //将数据存储到redis
        redisTools.set(Constants.GOODS_PREFIX+id,goodsVO);
        return RespResult.ok(goodsVO);
    }


    private void  toSnapupGoods(String goodsId, String userId) throws Exception {

        //2判断用户是否已经抢购:根据用户编号和商品编号以及支付状态查询是否存在数据
        //从redis中查询该用户是否已经抢购国该商品
        //设置线程锁：
       /* while (!redisTools.lock(Constants.GET_GOODS_LOCK+":"+goodsId,
                Constants.GET_GOODS_LOCK_EXPIRE)){
            Thread.sleep(2000);
        }*/
        Object isSnapuped = redisTools.get(Constants.GOODS_PREFIX + goodsId + ":" + userId);
        if(EmptyUtils.isNotEmpty(isSnapuped)){//说明该用户已经抢购过该商品了
            //将该用户已经抢购过该商品的处理结果存储到redis中
            redisTools.set(Constants.GOODS_PREFIX+goodsId+":"+userId,Constants.SnapupGoodsStatus.GOODS_SNAPUPED);
            //redisTools.unlock(Constants.GET_GOODS_LOCK+":"+goodsId);//释放线程锁
            return;
        }
        //如果代码走到这里说明获取了线程锁
        //3判断库存
        //从redis中获取商品库存信息
        QgGoodsVO goodsVo = redisTools.getObject(Constants.GOODS_PREFIX + goodsId, QgGoodsVO.class);
        //判断商品库存信息
        if(goodsVo.getCurrentStock()<=0){
            //将该商品库存不足的处理结果存储到redis中
            redisTools.set(Constants.GOODS_PREFIX+goodsId+":"+userId,Constants.SnapupGoodsStatus.GOODS_UNDER_STOCK);
            //redisTools.unlock(Constants.GET_GOODS_LOCK+":"+goodsId);//释放线程锁
            return;
        }
        //4保存用户抢购信息，更新库存信息
        //保存用户的抢购信息导数据库中：
        QgGoodsTempStock tempStock = new QgGoodsTempStock();
        String stockId = IdWorker.getId();
        tempStock.setId(stockId);
        tempStock.setUserId(userId);
        tempStock.setGoodsId(goodsId);
        tempStock.setStatus(Constants.PayStatus.LOCK_STOCK);
        tempStock.setCreatedTime(new Date());
        tempStock.setUpdatedTime(new Date());
        qgGoodsTempStockService.qdtxAddQgGoodsTempStock(tempStock);
        //将当前用户抢购到的商品的抢购信息存入redis
        redisTools.set(Constants.GOODS_PREFIX+goodsId+":"+userId,
                Constants.SnapupGoodsStatus.GOODS_SNAPUP_SUCCESS);
        //更新redis中的库存:
        goodsVo.setCurrentStock(goodsVo.getCurrentStock()-1);
        redisTools.set(Constants.GOODS_PREFIX+goodsId,goodsVo);
        //5生成订单
        // TODO
        createOrder(goodsId,userId,stockId,goodsVo.getPrice());
        //redisTools.unlock(Constants.GET_GOODS_LOCK+":"+goodsId);//释放线程锁
    }

    private void createOrder(String goodsId,String userId,String stockId,Double price) throws Exception {
        QgOrder qgOrder = new QgOrder();
        qgOrder.setAmount(price);
        qgOrder.setCreatedTime(new Date());
        qgOrder.setGoodsId(goodsId);
        qgOrder.setId(IdWorker.getId());
        qgOrder.setNum(1);
        qgOrder.setOrderNo(IdWorker.getId());
        qgOrder.setStatus(Constants.PayStatus.LOCK_STOCK);
        qgOrder.setStockId(stockId);//临时库存表中的主键值
        qgOrder.setUpdatedTime(new Date());
        qgOrder.setUserId(userId);
        qgOrderService.qdtxAddQgOrder(qgOrder);
    }

    /**
     * 将抢购商品的消息发送到消息中间件中
     * @param goodsId
     * @param token
     * @return
     * @throws Exception
     */
    @Override
    public RespResult snapupGoodsMessageSendToActiveMQ(String goodsId, String token) throws Exception {
        //1.获取用户信息
        QgUser qgUser = redisTools.getObject(token,QgUser.class);
        //2.创建SnapupGoodsVO对象
        SnapupGoodsVO goodsVO = new SnapupGoodsVO();
        goodsVO.setGoodId(goodsId);
        goodsVO.setUserId(qgUser.getId());
        goodsVO.setCreationDate(new Date());
        //3.将消息发送到消息中间件中
        activeMQutil.sendMessage(Constants.GET_GOODS,goodsVO);
        //返回结果
        return RespResult.build(GoodsException.GET_GOODS_WAIT.getCode(),
                GoodsException.GET_GOODS_WAIT.getMessage());
    }

    @Override
    public RespResult flushGoodsSnapupResult(String goodsId, String token) throws Exception {
        //1.获取用户信息
        QgUser qgUser = redisTools.getObject(token,QgUser.class);
        //2.根据商品编号和用户编号查询商品抢购状态
        Integer status = redisTools.getObject(Constants.GOODS_PREFIX+goodsId+":"+qgUser.getId(),Integer.class);
        RespResult respResult = null;
        switch (status){
            case 0:
                respResult = RespResult.build(GoodsException.USER_BUY_GOODS_YET.getCode(),
                        GoodsException.USER_BUY_GOODS_YET.getMessage());
                break;
            case 1:
                respResult = RespResult.build(GoodsException.NO_GOODS_STOCK.getCode(),
                        GoodsException.NO_GOODS_STOCK.getMessage());
                break;
            case 2:
                respResult = RespResult.build(GoodsException.GOODS_SNAPUP_SUCCESS.getCode(),
                        GoodsException.GOODS_SNAPUP_SUCCESS.getMessage());
                break;
        }
        return respResult;
    }

    /**
     * 监听消息中间件中抢购商品的消息，并处理
     * @param goodsVO
     * @throws Exception
     */
    @JmsListener(destination = Constants.GET_GOODS)
    public void dealsnapupGoodsMessage(SnapupGoodsVO goodsVO) throws Exception{
        this.toSnapupGoods(goodsVO.getGoodId(),goodsVO.getUserId());
    }
}
